/*
 * Copyright (C) 2012-2016 YunBo(ShenZhen) Co.,Ltd. All right reserved.
 * @version V1.0
 */
package com.wu.foodsafetyplayer.http;

import android.annotation.SuppressLint;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.JsonIOException;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.URL;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class Func {

    // private static final int CORES =
    // Runtime.getRuntime().availableProcessors();
    // private static final int POOL_SIZE = CORES + 1;
    // private static final int POOL_SIZE_MAX = CORES * 2 + 1;
    private static final BlockingQueue<Runnable> POOL_QUEUE_TASK = new SynchronousQueue<Runnable>();
    private static final ThreadFactory TASK_FACTORY = new ThreadFactory() {
        private final AtomicInteger COUNT = new AtomicInteger(1);

        public Thread newThread(Runnable runnable) {
            int count = COUNT.getAndIncrement();
            return new Thread(runnable, "Func #" + count);
        }
    };
    public static final ExecutorService FUNC_TASK = new ThreadPoolExecutor(8,
            Integer.MAX_VALUE, 3L, TimeUnit.SECONDS, POOL_QUEUE_TASK,
            TASK_FACTORY);

    @SuppressWarnings("deprecation")
    public static HttpURLConnection getHttpURLConnection(String urlString) {
        if (TextUtils.isEmpty(urlString)) {
            return null;
        }
        try {
            URL url = new URL(urlString);
            HttpURLConnection httpURLConnection = null;
            if (TextUtils.isEmpty(android.net.Proxy.getDefaultHost())) {
                httpURLConnection = (HttpURLConnection) url.openConnection();
            } else {
                if (urlString.startsWith("http://127.0.0.1")) {
                    Log.e("getHttpURLConnection", "http://127.0.0.1");
                    httpURLConnection = (HttpURLConnection) url
                            .openConnection(Proxy.NO_PROXY);
                } else {
                    httpURLConnection = (HttpURLConnection) url
                            .openConnection(new Proxy(Type.HTTP,
                                    new InetSocketAddress(android.net.Proxy
                                            .getDefaultHost(),
                                            android.net.Proxy.getDefaultPort())));
                }
            }
            httpURLConnection.setConnectTimeout(3000);
            httpURLConnection.setReadTimeout(3000);
            return httpURLConnection;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    @SuppressLint("SdCardPath")
    public static final String TVEYEINFOS_FILE_PATH = "/data/data/%s/files/tveyeinfos.json";

    public static String postImplRequest(Context context, String urlString,
                                         String postParam) {
        try {
            HttpURLConnection hc = getHttpURLConnection(urlString);
            if (hc == null) {
                return null;
            }
            hc.setDoOutput(true);
            hc.setDoInput(true);
            hc.setUseCaches(false);
            hc.setRequestMethod("POST");
            hc.setRequestProperty("Content-Type", "application/octet-stream");

            byte[] bits = postParam.getBytes("UTF-8");
            if (bits != null) {
                hc.setRequestProperty("Content-Length", bits.length + "");
            }
            OutputStream out = hc.getOutputStream();
            if (bits != null) {
                out.write(bits);
                out.flush();
            }
            InputStream input = hc.getInputStream();
            ByteArrayOutputStream byteArr = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int k = 0;
            while ((k = input.read(bytes)) != -1) {
                byteArr.write(bytes, 0, k);
            }
            byteArr.flush();
            byte[] returnDatas = byteArr.toByteArray();
            byteArr.close();
            input.close();
            out.close();
            String result = new String(returnDatas, "UTF-8");
            writeFile(
                    String.format(TVEYEINFOS_FILE_PATH,
                            context.getApplicationInfo().packageName), result,
                    false);
            return result;
        } catch (ProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonIOException e) {
            // TODO: handle exception
            e.printStackTrace();
        } catch (JsonSyntaxException e) {
            // TODO: handle exception
            e.printStackTrace();
        } catch (JsonParseException e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return null;
    }

    /**
     * get 请求
     *
     * @param context
     * @param urlString
     * @return
     */
    public static String getBackRequest(Context context, String urlString) {

        try {
            URL url = new URL(urlString);
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            // 设置请求的模式
            connection.setRequestMethod("GET");
            // 设置请求连接超时时间
            connection.setConnectTimeout(5000);
            // 设置访问时的超时时间
            connection.setReadTimeout(5000);
            // 开启连接
            connection.connect();
            InputStream inputStream = null;
            BufferedReader reader = null;
            // 如果应答码为200的时候，表示成功的请求带了，这里的HttpURLConnection.HTTP_OK就是200
            String result = null;
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                // 获得连接的输入流
                inputStream = connection.getInputStream();
                // 转换成一个加强型的buffered流
                reader = new BufferedReader(new InputStreamReader(inputStream));
                // 把读到的内容赋值给result
                result = reader.readLine();
            }
            reader.close();
            inputStream.close();
            connection.disconnect();
            return result;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static boolean downLoad(Context context, String url, File file,
                                   File tmpFile, long offset) {
        HttpURLConnection connection = getHttpURLConnection(url);
        try {
            connection.setRequestMethod("GET");
            connection.setRequestProperty("RANGE", "bytes=" + offset + "-");
            RandomAccessFile randomAccess = null;
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                randomAccess = getRandomAccessFile(tmpFile, 0);
            } else if (connection.getResponseCode() == HttpURLConnection.HTTP_PARTIAL) {
                randomAccess = getRandomAccessFile(tmpFile, offset);
            }
            // Log.e("ddddddddddddddddd", "" + connection.getResponseCode());
            InputStream inputStream = connection.getInputStream();
            byte[] buffer = new byte[1024 * 8];
            int len = -1;
            while ((len = inputStream.read(buffer)) != -1) {
                randomAccess.write(buffer, 0, len);
            }
            randomAccess.close();
            tmpFile.renameTo(file);
            return true;
        } catch (ProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }
    }

    public static RandomAccessFile getRandomAccessFile(File file, long offset)
            throws IOException {
        RandomAccessFile raf = new RandomAccessFile(file, "rwd");
        raf.seek(offset);
        return raf;
    }

    public static String getMac() {
        String macString = "not augesion box";
        try {
            InputStream localInputStream = Runtime.getRuntime()
                    .exec("cat /sys/class/net/eth0/address").getInputStream();
            InputStreamReader localInputStreamReader = new InputStreamReader(
                    localInputStream);
            BufferedReader localBufferedReader = new BufferedReader(
                    localInputStreamReader);
            String str2 = localBufferedReader.readLine();
            if (str2 != null) {
                macString = str2;
            }
            localBufferedReader.close();
            localInputStreamReader.close();
            localInputStream.close();
            String str3 = ((String) macString).toUpperCase();
            if (str3 != null) {
                macString = str3;
            }
        } catch (IOException localIOException) {
            localIOException.printStackTrace();
            macString = "not augesion box";
        }
        return macString;
    }

    /**
     * 获取assets的数据 init
     *
     * @param context
     * @param fileName
     * @return
     */
    public static String getAssetsServer(Context context, String fileName) {
        InputStream inputStream;
        InputStreamReader inputStreamReader;
        BufferedReader bufferedReader;
        try {
            StringBuilder stringBuilder = new StringBuilder();
            inputStream = context.getAssets().open("server.json");
            if (inputStream != null) {
                inputStreamReader = new InputStreamReader(inputStream);
                bufferedReader = new BufferedReader(inputStreamReader);
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    stringBuilder.append(line);
                }
            }
            if (!TextUtils.isEmpty(stringBuilder.toString())) {
                JSONObject jsonObject = new JSONObject(stringBuilder.toString());
                String result = jsonObject.optString(fileName, "");
                return result;
            }
        } catch (IOException | JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "";
        }
        return "";
    }

    /**
     * write file 追加内容/清楚重写
     *
     * @param filePath
     * @param content
     * @param append   is append, if true, write to the end of file, else clear
     *                 content of file and write into it
     * @return return false if content is empty, true otherwise
     * @throws RuntimeException if an error occurs while operator FileWriter
     */
    public static boolean writeFile(String filePath, String content,
                                    boolean append) {
        if (content == null || content.length() == 0) {
            return false;
        }

        FileWriter fileWriter = null;
        try {
            makeDirs(filePath);
            fileWriter = new FileWriter(filePath, append);
            fileWriter.write(content);
            return true;
        } catch (IOException e) {
            throw new RuntimeException("IOException occurred. ", e);
        } finally {
            close(fileWriter);
        }
    }

    public static boolean makeDirs(String filePath) {
        String folderName = getFolderName(filePath);
        if (folderName == null || folderName.length() == 0) {
            return false;
        }

        File folder = new File(folderName);
        return (folder.exists() && folder.isDirectory()) ? true : folder
                .mkdirs();
    }

    public static String getFolderName(String filePath) {

        if (filePath == null || filePath.length() == 0) {
            return filePath;
        }

        int filePosi = filePath.lastIndexOf(File.separator);
        return (filePosi == -1) ? "" : filePath.substring(0, filePosi);
    }

    /**
     * read file 读取文件
     *
     * @param filePath
     * @param charsetName The name of a supported {@link java.nio.charset.Charset
     *                    </code>charset<code>}
     * @return if file not exist, return null, else return content of file
     * @throws RuntimeException if an error occurs while operator BufferedReader
     */
    public static StringBuilder readFile(String filePath, String charsetName) {
        File file = new File(filePath);
        StringBuilder fileContent = new StringBuilder("");
        if (file == null || !file.isFile()) {
            return null;
        }

        BufferedReader reader = null;
        try {
            InputStreamReader is = new InputStreamReader(new FileInputStream(
                    file), charsetName);
            reader = new BufferedReader(is);
            String line = null;
            while ((line = reader.readLine()) != null) {
                if (!fileContent.toString().equals("")) {
                    fileContent.append("\r\n");
                }
                fileContent.append(line);
            }
            return fileContent;
        } catch (IOException e) {
            throw new RuntimeException("IOException occurred. ", e);
        } finally {
            close(reader);
        }
    }

    /**
     * Close closable object and wrap {@link IOException} with
     * {@link RuntimeException}
     *
     * @param closeable closeable object
     */
    public static void close(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                throw new RuntimeException("IOException occurred. ", e);
            }
        }
    }
}
